use super::Result;
use axum::async_trait;
use lazy_static::lazy_static;
use rbatis::crud::{CRUDTable, CRUD};
use rbatis::rbatis::Rbatis;
use rbatis::wrapper::Wrapper;
use serde::de::DeserializeOwned;
use serde::Serialize;
use async_std::sync::{RwLock};
use rbatis::Uuid;


lazy_static! {
    pub static ref RB: RwLock<Rbatis> = RwLock::new(Rbatis::new());
}

#[async_trait]
pub trait DAOBase {
    fn get_id(&self) -> &Option<Uuid>;
    async fn save(&self) -> Result<Self>
        where
            Self: CRUDTable + Sized + Clone,
    {
        RB.read().await.save(self, &[]).await?;
        Ok((*self).clone())
    }
    async fn delete(&self) -> Result<()>
        where
            Self: CRUDTable + Sized,
    {
        RB.read().await.remove_by_column::<Self, _>("id", &self.get_id()).await?;
        Ok(())
    }

    async fn get<P>(id: P) -> Option<Self>
        where
            Self: CRUDTable + DeserializeOwned,
            P: Serialize + Send + Sync,
    {
        RB.read().await.fetch_by_column("id", id).await.unwrap()
    }

    async fn all() -> Vec<Self>
        where
            Self: CRUDTable + DeserializeOwned,
    {
        RB.read().await.fetch_list().await.unwrap()
    }

    async fn filter(query: Wrapper) -> Vec<Self>
        where
            Self: CRUDTable + DeserializeOwned,
    {
        RB.read().await.fetch_list_by_wrapper(query).await.unwrap_or_default()
    }

    async fn update(&self) -> Result<Self>
        where
            Self: CRUDTable + DeserializeOwned + Clone,
    {
        RB.read().await.update_by_column("id", &self).await?;
        Ok((*self).clone())
    }
}

#[cfg(test)]
mod tests {
    use rbatis::{crud_table, Uuid};
    use rbatis::logic_delete::RbatisLogicDeletePlugin;
    use crate::db::RB;
    use macros::curd_entry;
    use crate::responses::CusResponse;
    use axum::response::IntoResponse;
    use axum::response::Response;

    use crate::db::DAOBase;

    #[curd_entry]
    #[crud_table]
    #[derive(Clone, Debug)]
    pub struct BizActivity {
        pub id: Option<Uuid>,
        pub name: Option<String>,
        pub delete_flag: bool,
    }

    // #[test]
    #[tokio::test]
    async fn it_works() {
        let plugin = RbatisLogicDeletePlugin::new("delete_flag");
        RB.write().await.set_logic_plugin(plugin);
        RB.read().await.link("mysql://root:123456@localhost:3306/test").await.unwrap();

        let mut activity = BizActivity {
            id: Some(Uuid::new()),
            name: Some("name".to_string()),
            delete_flag: false,
        };
        // 新增
        match activity.save().await {
            Ok(ok) => {
                println!("新增 ok: {:?}", ok);
            }
            Err(err) => {
                println!("新增 err: {}", err);
            }
        }

        activity.name = Some("new_name".to_string());

        // 修改
        // match activity.update().await {
        //     Ok(ok) => {
        //         println!("修改 ok: {:?}", ok);
        //     }
        //     Err(err) => {
        //         println!("修改 err: {}", err);
        //     }
        // }
        // 删除
        match activity.delete().await {
            Ok(ok) => {
                println!("删除 ok: {:?}", ok);
            }
            Err(err) => {
                println!("删除 err: {}", err);
            }
        }
    }
}